{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\n",
    "import os\n",
    "\n",
    "import time\n",
    "from datetime import datetime\n",
    "from alibi_detect.od import SpectralResidual"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "def get_data():\n",
    "    data_path = '../../../../data/train_data/host'\n",
    "    dfs = {}\n",
    "    for file in os.listdir(data_path):\n",
    "        print('Reading ' + file)\n",
    "        dfs[file[:-4]] = pd.read_csv(data_path+'/'+file) \n",
    "    return dfs\n",
    "\n",
    "def load_tiago_test(test):\n",
    "    data_path = '../../../../data/tiago_tests/test'\n",
    "    df = pd.read_csv(data_path+str(test)+'/kpis.csv')\n",
    "    return df\n",
    "\n",
    "def load_test():\n",
    "    data_path = '../../../../data/test_data/host'\n",
    "    df = pd.DataFrame(['item_id','name','bomc_id','timestamp','value','cmdb_id'])\n",
    "    for file in os.listdir(data_path):\n",
    "        df = pd.concat([df, pd.read_csv(data_path+'/'+file)], ignore_index=True) \n",
    "    return df"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {
    "tags": [
     "outputPrepend"
    ]
   },
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0\n",
      " 0 0 1 1 0 0 0 0]\n",
      "ST Threshold Anomaly!\n",
      "Determining threshold for ('redis_008', 'used_cpu_sys')\n",
      "Determining threshold for ('redis_008', 'used_cpu_user')\n",
      "Determining threshold for ('redis_008', 'used_memory')\n",
      "Determining threshold for ('redis_009', 'connected_clients')\n",
      "Determining threshold for ('redis_009', 'instantaneous_input_kbps')\n",
      "Determining threshold for ('redis_009', 'instantaneous_ops_per_sec')\n",
      "Determining threshold for ('redis_009', 'instantaneous_output_kbps')\n",
      "Determining threshold for ('redis_009', 'keyspace_hits')\n",
      "[1 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0\n",
      " 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0\n",
      " 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0\n",
      " 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0\n",
      " 0 0 1 1 0 0 0 0]\n",
      "ST Threshold Anomaly!\n",
      "Determining threshold for ('redis_009', 'keyspace_misses')\n",
      "[1 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0\n",
      " 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0\n",
      " 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0\n",
      " 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0\n",
      " 0 0 1 1 0 0 0 0]\n",
      "ST Threshold Anomaly!\n",
      "Determining threshold for ('redis_009', 'mem_fragmentation_ratio')\n",
      "Determining threshold for ('redis_009', 'total_commands_processed')\n",
      "Determining threshold for ('redis_009', 'total_connections_received')\n",
      "[1 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0\n",
      " 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0\n",
      " 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0\n",
      " 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0\n",
      " 0 0 1 1 0 0 0 0]\n",
      "ST Threshold Anomaly!\n",
      "Determining threshold for ('redis_009', 'used_cpu_sys')\n",
      "Determining threshold for ('redis_009', 'used_cpu_user')\n",
      "Determining threshold for ('redis_009', 'used_memory')\n",
      "Determining threshold for ('redis_010', 'instantaneous_input_kbps')\n",
      "Determining threshold for ('redis_010', 'instantaneous_ops_per_sec')\n",
      "Determining threshold for ('redis_010', 'instantaneous_output_kbps')\n",
      "Determining threshold for ('redis_010', 'mem_fragmentation_ratio')\n",
      "Determining threshold for ('redis_010', 'total_commands_processed')\n",
      "Determining threshold for ('redis_010', 'total_connections_received')\n",
      "[1 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0\n",
      " 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0\n",
      " 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0\n",
      " 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0\n",
      " 0 0 1 1 0 0 0 0]\n",
      "ST Threshold Anomaly!\n",
      "Determining threshold for ('redis_010', 'used_cpu_sys')\n",
      "Determining threshold for ('redis_010', 'used_cpu_user')\n",
      "Determining threshold for ('redis_010', 'used_memory')\n",
      "Determining threshold for ('redis_011', 'instantaneous_input_kbps')\n",
      "Determining threshold for ('redis_011', 'instantaneous_ops_per_sec')\n",
      "Determining threshold for ('redis_011', 'instantaneous_output_kbps')\n",
      "Determining threshold for ('redis_011', 'mem_fragmentation_ratio')\n",
      "Determining threshold for ('redis_011', 'total_commands_processed')\n",
      "Determining threshold for ('redis_011', 'total_connections_received')\n",
      "[1 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0\n",
      " 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0\n",
      " 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0\n",
      " 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0\n",
      " 0 0 1 1 0 0 0 0]\n",
      "ST Threshold Anomaly!\n",
      "Determining threshold for ('redis_011', 'used_cpu_sys')\n",
      "Determining threshold for ('redis_011', 'used_cpu_user')\n",
      "Determining threshold for ('redis_011', 'used_memory')\n",
      "Determining threshold for ('redis_012', 'connected_clients')\n",
      "Anomaly,  std in train was 0, now its not\n",
      "Determining threshold for ('redis_012', 'instantaneous_input_kbps')\n",
      "Determining threshold for ('redis_012', 'instantaneous_ops_per_sec')\n",
      "[1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 1 0 0 0 0]\n",
      "ST Threshold Anomaly!\n",
      "Determining threshold for ('redis_012', 'instantaneous_output_kbps')\n",
      "Determining threshold for ('redis_012', 'keyspace_hits')\n",
      "Anomaly,  std in train was 0, now its not\n",
      "Determining threshold for ('redis_012', 'mem_fragmentation_ratio')\n",
      "Anomaly,  std in train was 0, now its not\n",
      "Determining threshold for ('redis_012', 'total_commands_processed')\n",
      "[0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0\n",
      " 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0\n",
      " 0 0 0 0 1 0 0 0]\n",
      "ST Threshold Anomaly!\n",
      "Determining threshold for ('redis_012', 'total_connections_received')\n",
      "[1 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0\n",
      " 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0\n",
      " 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0\n",
      " 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0\n",
      " 0 0 1 1 0 0 0 0]\n",
      "ST Threshold Anomaly!\n",
      "Determining threshold for ('redis_012', 'used_cpu_sys')\n",
      "Determining threshold for ('redis_012', 'used_cpu_user')\n",
      "Determining threshold for ('redis_012', 'used_memory')\n",
      "It took 13.102717161178589 seconds to find 162 anomalies\n",
      "[('ACS', 'db_001'), ('tnsping_result_time', 'db_001'), ('Asm_Free_Tb', 'db_002'), ('Login_Per_Sec', 'db_002'), ('New_Tbs_Free_Gb', 'db_002'), ('New_Tbs_Used_Pct', 'db_002'), ('SctRead_Per_Sec', 'db_004'), ('MEM_Total', 'db_005'), ('MEM_Used', 'db_005'), ('MEM_Used_Pct', 'db_005'), ('MEM_real_util', 'db_005'), ('New_Tbs_Free_Gb', 'db_005'), ('New_Tbs_Used_Pct', 'db_005'), ('SctRead_Per_Sec', 'db_005'), ('Asm_Free_Tb', 'db_006'), ('Login_Per_Sec', 'db_006'), ('New_Tbs_Free_Gb', 'db_006'), ('New_Tbs_Used_Pct', 'db_006'), ('AIOS', 'db_007'), ('Asm_Free_Tb', 'db_007'), ('DFParaWrite_Per_Sec', 'db_007'), ('MEM_Total', 'db_007'), ('MEM_real_util', 'db_007'), ('New_Tbs_Free_Gb', 'db_007'), ('New_Tbs_Used_Pct', 'db_007'), ('New_Tbs_Used_Pct', 'db_008'), ('SctRead_Per_Sec', 'db_008'), ('SeqRead_Per_Sec', 'db_008'), ('Exec_Per_Sec', 'db_009'), ('New_Tbs_Used_Pct', 'db_009'), ('Redo_Per_Sec', 'db_009'), ('User_Commit', 'db_009'), ('tnsping_result_time', 'db_009'), ('AIOS', 'db_010'), ('Asm_Free_Tb', 'db_010'), ('MEM_Used_Pct', 'db_010'), ('New_Tbs_Free_Gb', 'db_010'), ('New_Tbs_Used_Pct', 'db_010'), ('SctRead_Per_Sec', 'db_010'), ('Sess_Active', 'db_010'), ('Asm_Free_Tb', 'db_011'), ('Call_Per_Sec', 'db_012'), ('Logic_Read_Per_Sec', 'db_012'), ('MEM_Total', 'db_012'), ('Sess_Active', 'db_012'), ('TPS_Per_Sec', 'db_012'), ('User_Commit', 'db_012'), ('MEM_Total', 'db_013'), ('SctRead_Per_Sec', 'db_013'), ('container_mem_used', 'docker_003'), ('container_mem_used', 'docker_004'), ('container_mem_used', 'docker_005'), ('container_mem_used', 'docker_006'), ('container_mem_used', 'docker_007'), ('FS_total_space', 'os_001'), ('Received_queue', 'os_001'), ('CPU_idle_pct', 'os_002'), ('Disk_rd_kbs', 'os_002'), ('FS_max_util', 'os_002'), ('FS_total_space', 'os_002'), ('Page_pi', 'os_002'), ('Disk_rd_ios', 'os_003'), ('Disk_rd_kbs', 'os_003'), ('FS_total_space', 'os_003'), ('Page_pi', 'os_003'), ('Disk_rd_ios', 'os_004'), ('FS_total_space', 'os_004'), ('Zombie_Process', 'os_004'), ('ss_total', 'os_004'), ('Disk_rd_ios', 'os_005'), ('Disk_rd_kbs', 'os_005'), ('FS_max_avail', 'os_005'), ('FS_max_util', 'os_005'), ('FS_total_space', 'os_005'), ('FS_used_pct', 'os_005'), ('FS_used_space', 'os_005'), ('Page_pi', 'os_005'), ('FS_total_space', 'os_006'), ('Memory_used', 'os_006'), ('Send_total', 'os_006'), ('Shared_memory', 'os_006'), ('ss_total', 'os_006'), ('FS_total_space', 'os_007'), ('Memory_available', 'os_007'), ('Memory_available_pct', 'os_007'), ('Memory_used', 'os_007'), ('Shared_memory', 'os_007'), ('FS_max_avail', 'os_008'), ('FS_total_space', 'os_008'), ('Num_of_running_processes', 'os_008'), ('Shared_memory', 'os_008'), ('Disk_rd_ios', 'os_009'), ('Memory_available_pct', 'os_009'), ('Disk_await', 'os_010'), ('FS_total_space', 'os_011'), ('Num_of_running_processes', 'os_011'), ('FS_total_space', 'os_012'), ('Incoming_network_traffic', 'os_012'), ('Buffers_used', 'os_013'), ('FS_total_space', 'os_013'), ('Recv_total', 'os_013'), ('Shared_memory', 'os_013'), ('FS_total_space', 'os_014'), ('Num_of_running_processes', 'os_014'), ('Shared_memory', 'os_014'), ('FS_total_space', 'os_015'), ('Processor_load_15_min', 'os_015'), ('Received_queue', 'os_015'), ('FS_total_space', 'os_016'), ('Num_of_running_processes', 'os_016'), ('Shared_memory', 'os_016'), ('System_block_queue_length', 'os_016'), ('Disk_rd_ios', 'os_017'), ('FS_max_util', 'os_017'), ('FS_total_space', 'os_017'), ('Memory_available_pct', 'os_017'), ('Received_queue', 'os_017'), ('Sent_queue', 'os_017'), ('Buffers_used', 'os_018'), ('Disk_rd_ios', 'os_018'), ('FS_max_util', 'os_018'), ('Received_queue', 'os_018'), ('FS_max_util', 'os_019'), ('Memory_available_pct', 'os_019'), ('Received_queue', 'os_019'), ('Disk_rd_ios', 'os_020'), ('FS_total_space', 'os_020'), ('FS_max_avail', 'os_021'), ('FS_used_pct', 'os_021'), ('FS_used_space', 'os_021'), ('Received_queue', 'os_022'), ('System_block_queue_length', 'os_022'), ('keyspace_hits', 'redis_001'), ('keyspace_misses', 'redis_001'), ('total_connections_received', 'redis_001'), ('keyspace_hits', 'redis_002'), ('keyspace_misses', 'redis_002'), ('total_connections_received', 'redis_002'), ('total_connections_received', 'redis_003'), ('connected_clients', 'redis_004'), ('keyspace_hits', 'redis_004'), ('total_connections_received', 'redis_004'), ('connected_clients', 'redis_005'), ('total_connections_received', 'redis_005'), ('used_cpu_user', 'redis_005'), ('total_connections_received', 'redis_006'), ('total_connections_received', 'redis_007'), ('connected_clients', 'redis_008'), ('keyspace_hits', 'redis_008'), ('mem_fragmentation_ratio', 'redis_008'), ('total_connections_received', 'redis_008'), ('keyspace_hits', 'redis_009'), ('keyspace_misses', 'redis_009'), ('total_connections_received', 'redis_009'), ('total_connections_received', 'redis_010'), ('total_connections_received', 'redis_011'), ('connected_clients', 'redis_012'), ('instantaneous_ops_per_sec', 'redis_012'), ('keyspace_hits', 'redis_012'), ('mem_fragmentation_ratio', 'redis_012'), ('total_commands_processed', 'redis_012'), ('total_connections_received', 'redis_012')]\n"
     ]
    }
   ],
   "source": [
    "def get_key_thresh(host):\n",
    "    df_thresh = pd.read_csv('thresh.csv')\n",
    "    df_thresh = df_thresh[df_thresh.host==host]\n",
    "\n",
    "    thresh = df_thresh[['name', 'thresh']].set_index('name')\n",
    "    thresh = thresh.to_dict()['thresh']\n",
    "    return thresh\n",
    "\n",
    "def find_anoms(hosts, df):\n",
    "    start = time.time()\n",
    "    kpis = dict(tuple(df.groupby(['cmdb_id', 'name'])))\n",
    "    res = {}\n",
    "    anoms = []\n",
    "    \n",
    "    df_info = pd.read_csv('/Users/baconbaker/Documents/Studium/ANM/anm-project/impl/models/kpi_detection/kpi_summary_info.data')\n",
    "    df_thresh = pd.read_csv('thresh.csv')\n",
    "\n",
    "    for key in kpis:\n",
    "        kpis[key]['timestamp'] = kpis[key]['timestamp'].apply(lambda x: datetime.fromtimestamp(x/1000.0))\n",
    "        kpis[key] = kpis[key].set_index('timestamp').sort_index()\n",
    "\n",
    "\n",
    "    per1_kpis = df_info[(df_info.interval=='1min') & (df_info.is_flat == False)]['kpi'].unique()\n",
    "    per5_kpis = df_info[(df_info.interval=='5min') & ((df_info.is_flat == False))]['kpi'].unique()\n",
    "\n",
    "    print('Calculating rolling window')\n",
    "    for key in kpis: \n",
    "        if key[0] in hosts:\n",
    "            if kpis[key]['value'].std() == 0:\n",
    "                continue\n",
    "            elif key[1] in per1_kpis:\n",
    "                d = kpis[key]['value'].resample('T').mean().interpolate()\n",
    "            elif key[1] in per5_kpis:\n",
    "                d = kpis[key]['value'].resample('5T').mean().interpolate()\n",
    "            else:\n",
    "                continue\n",
    "            d = (d - d.mean())/d.std()\n",
    "            res[key] = d.rolling(10).mean()\n",
    "\n",
    "\n",
    "    for key in res:\n",
    "        print('Determining threshold for', key)\n",
    "        if len(df_thresh[(df_thresh.host == key[0]) & (df_thresh.name==key[1])]) == 0:\n",
    "            print('Anomaly,  std in train was 0, now its not')\n",
    "            anoms.append((key[1],key[0]))\n",
    "            continue\n",
    "        thresh = df_thresh[(df_thresh.host == key[0]) & (df_thresh.name==key[1])]['thresh'].values[0]\n",
    "        d = res[key].dropna()\n",
    "        od = SpectralResidual(\n",
    "                threshold=thresh,\n",
    "                window_amp=10,\n",
    "                window_local=10,\n",
    "                n_est_points=5,\n",
    "                n_grad_points=5\n",
    "            )\n",
    "        if len(d) == 0:\n",
    "            print('Rolling window data empty! Skipping')\n",
    "            continue\n",
    "        outliers = od.predict(d.values)['data']\n",
    "        if np.sum(np.sum(outliers['is_outlier'][-5:-2])) > 0:\n",
    "            print(outliers['is_outlier'])\n",
    "            print(\"ST Threshold Anomaly!\")\n",
    "            anoms.append((key[1],key[0]))\n",
    "    print(\"It took\", time.time()-start, \"seconds to find\", len(anoms),\"anomalies\")\n",
    "    return anoms\n",
    "\n",
    "print(find_anoms(load_test().cmdb_id.unique(), load_test()))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [],
   "source": [
    "df = load_test()\n",
    "df = df[(df.cmdb_id == 'os_006') & (df.name == 'Received_packets')]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "   # start = time.time()\n",
    "    # anoms = []\n",
    "    # for host in hosts:\n",
    "    #     start_host = time.time()\n",
    "    #     print('*'*60)\n",
    "    #     print('Checking ', host)\n",
    "    #     thresholds = get_key_thresh(host)\n",
    "    #     for kpi in thresholds:\n",
    "    #         thresh = thresholds[kpi]\n",
    "    #         print('Threshold ', thresh, kpi)\n",
    "    #         od = SpectralResidual(\n",
    "    #             threshold=thresh,\n",
    "    #             window_amp=10,\n",
    "    #             window_local=10,\n",
    "    #             n_est_points=5,\n",
    "    #             n_grad_points=5\n",
    "    #         )\n",
    "\n",
    "    #         df_hk = df[df.cmdb_id == host][df.name == kpi]\n",
    "            \n",
    "    #         if len(df_hk) == 0:\n",
    "    #             print('No valid data to use, skipping')\n",
    "    #             continue\n",
    "                \n",
    "    #         data = get_past(df_hk, np.max(df_hk.timestamp.unique()), 30)['value']\n",
    "    #         data = np.concatenate([data, data])\n",
    "            \n",
    "    #         if thresh == -1:\n",
    "    #             if data[-1] > 0:\n",
    "    #                 print(\"Non-Zero Anomaly!\")\n",
    "    #                 anoms.append((host, kpi))\n",
    "    #         elif np.isnan(thresh):\n",
    "    #             print('NaN, Skipping!')\n",
    "    #         else:\n",
    "    #             outliers = od.predict(data)['data']\n",
    "    #             print(outliers['instance_score'])\n",
    "    #             if np.mean(data) == 0 or np.std(data) == 0:\n",
    "    #                 print(\"Mean is zero or std is zero\")\n",
    "    #                 anoms.append((host,kpi))\n",
    "    #             if np.sum(outliers['is_outlier'][-31:-30]) > 0:\n",
    "    #                 print(outliers['is_outlier'])\n",
    "    #                 print(\"ST Threshold Anomaly!\")\n",
    "    #                 anoms.append((host,kpi))\n",
    "    #     print(host, ' completed in ', time.time() - start_host)\n",
    "    # print('Completed detection of ', len(hosts), 'hosts in ', time.time() - start, 'seconds')\n",
    "    # return anoms"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.5-final"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}